/**
 * Copyright (C) 2013 The CyanogenMod Project
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.whispersystems.whisperpush.ui;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import org.whispersystems.textsecure.crypto.IdentityKey;
import org.whispersystems.textsecure.crypto.InvalidKeyException;
import org.whispersystems.textsecure.crypto.InvalidMessageException;
import org.whispersystems.textsecure.crypto.InvalidVersionException;
import org.whispersystems.textsecure.crypto.MasterSecret;
import org.whispersystems.textsecure.crypto.protocol.PreKeyWhisperMessage;
import org.whispersystems.textsecure.push.IncomingPushMessage;
import org.whispersystems.whisperpush.R;
import org.whispersystems.whisperpush.contacts.Contact;
import org.whispersystems.whisperpush.crypto.MasterSecretUtil;
import org.whispersystems.whisperpush.crypto.MessagePeer;
import org.whispersystems.whisperpush.database.DatabaseFactory;
import org.whispersystems.whisperpush.database.PendingApprovalDatabase;
import org.whispersystems.whisperpush.service.MessageNotifier;
import org.whispersystems.whisperpush.service.SendReceiveService;

public class VerifyIdentityActivity extends KeyScanningActivity {

  private Contact contact;

  public void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    getActionBar().setDisplayHomeAsUpEnabled(true);
    setContentView(R.layout.verify_identity_activity);

    initializeResources();
  }

  private void initializeResources() {
    ImageView imageView       = (ImageView) findViewById(R.id.avatar              );
    TextView  contactText     = (TextView ) findViewById(R.id.contact_name        );
    TextView  fingerprintText = (TextView ) findViewById(R.id.identity_fingerprint);
    Button    validButton     = (Button   ) findViewById(R.id.valid_button        );
    Button    invalidButton   = (Button   ) findViewById(R.id.invalid_button      );

    contact = getIntent().getParcelableExtra("contact");

    imageView.setImageBitmap(contact.getAvatar());
    contactText.setText(contact.toShortString());
    fingerprintText.setText(identityKey.getFingerprint());
    validButton.setOnClickListener(new MarkValidListener());
    invalidButton.setOnClickListener(new MarkInvalidListener());
  }

  private class MarkValidListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
      new ReleaseMatchingKeysTask(VerifyIdentityActivity.this, identityKey, contact).execute();
    }
  }

  private class MarkInvalidListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
      final Context context = VerifyIdentityActivity.this;
      AlertDialog.Builder builder = new AlertDialog.Builder(context);
      builder.setTitle(getString(R.string.VerifyIdentityActivity_discard_messages));
      builder.setMessage(getString(R.string.VerifyIdentityActivity_are_you_sure_you_would_like_to_mark_this_identity_fingerprint_as_invalid_and_discard));
      builder.setIcon(android.R.drawable.ic_dialog_alert);
      builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          new DiscardMatchingKeysTask(VerifyIdentityActivity.this, contact, identityKey).execute();
        }
      });
      builder.setNegativeButton(android.R.string.cancel, null);
      builder.show();
    }
  }

  private class DiscardMatchingKeysTask extends AsyncTask<Void, Void, Void> {

    private final Context      context;
    private final Contact      contact;
    private final IdentityKey  identityKey;

    private ProgressDialog progressDialog;

    public DiscardMatchingKeysTask(Context context, Contact contact, IdentityKey identityKey) {
      this.context      = context;
      this.contact      = contact;
      this.identityKey  = identityKey;
    }

    @Override
    protected void onPreExecute() {
      progressDialog = ProgressDialog.show(context,
                                           getString(R.string.VerifyIdentityActivity_processing),
                                           getString(R.string.VerifyIdentityActivity_discarding_messages));
    }

    @Override
    protected Void doInBackground(Void... params) {
      final PendingApprovalDatabase database = DatabaseFactory.getPendingApprovalDatabase(context);

      Cursor cursor = null;

      try {
        cursor = database.getPending(contact.getNumber());

        PendingApprovalDatabase.Reader reader = database.readerFor(cursor);
        IncomingPushMessage message;

        while ((message = reader.getNext()) != null) {
          try {
            PreKeyWhisperMessage keyExchangeMessage = new PreKeyWhisperMessage(message.getBody());

            if (keyExchangeMessage.getIdentityKey().equals(identityKey)) {
              database.delete(reader.getCurrentId());
            }
          } catch (InvalidVersionException e) {
            Log.w("VerifyIdentityActivity", e);
          } catch (InvalidMessageException e) {
            Log.w("VerifyIdentityActivity", e);
          }
        }
      } finally {
        if (cursor != null)
          cursor.close();
      }

      MessageNotifier.updateNotifications(context);
      return null;
    }

    @Override
    protected void onPostExecute(Void result) {
      if (progressDialog != null)
        progressDialog.dismiss();

      finish();
    }
  }

  private class ReleaseMatchingKeysTask extends AsyncTask<Void, Void, Void> {

    private final Context     context;
    private final MasterSecret masterSecret;
    private final IdentityKey identityKey;
    private final Contact     contact;

    private ProgressDialog progressDialog;

    public ReleaseMatchingKeysTask(Context context,
                                   IdentityKey identityKey,
                                   Contact contact)
    {
      this.context     = context;
      this.masterSecret = MasterSecretUtil.getMasterSecret(context);
      this.identityKey = identityKey;
      this.contact     = contact;
    }

    @Override
    protected void onPreExecute() {
      progressDialog = ProgressDialog.show(context,
                                           getString(R.string.VerifyIdentityActivity_processing),
                                           getString(R.string.VerifyIdentityActivity_processing_identity_key),
                                           true, false);
    }

    @Override
    protected Void doInBackground(Void... params) {
      PendingApprovalDatabase database = DatabaseFactory.getPendingApprovalDatabase(context);
      MessagePeer             address  = new MessagePeer(context, contact.getNumber());

      DatabaseFactory.getIdentityDatabase(context).saveIdentity(masterSecret, address, identityKey);

      Cursor                         cursor = database.getPending(contact.getNumber());
      PendingApprovalDatabase.Reader reader = database.readerFor(cursor);

      IncomingPushMessage message;

      while ((message = reader.getNext()) != null) {
        try {
          PreKeyWhisperMessage keyExchange = new PreKeyWhisperMessage(message.getBody());

          if (keyExchange.getIdentityKey().equals(identityKey)) {
            Intent intent = new Intent(context, SendReceiveService.class);
            intent.setAction(SendReceiveService.RECEIVE_SMS);
            intent.putExtra("message", message);
            context.startService(intent);
            database.delete(reader.getCurrentId());
          }
        } catch (InvalidVersionException e) {
          Log.w("VerifyIdentityActivity", e);
        } catch (InvalidMessageException e) {
          Log.w("VerifyIdentityActivity", e);
        }
      }

      MessageNotifier.updateNotifications(context);
      return null;
    }

    @Override
    protected void onPostExecute(Void results) {
      if (progressDialog != null)
        progressDialog.dismiss();

      finish();
    }
  }
}
